package com.neuronrobotics.replicator.gui.preview.controller;

import android.util.Log;

import com.neuronrobotics.replicator.gui.preview.model.STLWorkspaceModel;

public interface STLPreviewMouseController {

	public enum MouseControlMode {

		CAMERA_ROTATE {

			@Override
			public void mouseDragged(ModeParameters params) {
				float scaleY, scaleZ;
				scaleY = scaleZ = 40.0f;

				float radY = params.yDist / scaleY;
				float radZ = params.xDist / scaleZ;

				params.theCameraController.revolveCameraXZ(radZ);
				params.theCameraController.revolveCameraUp(radY);
			}

			public String toString() {
				return "Camera Rotate";
			}

		},
		MODEL_ROTATE_X {

			@Override
			public void mouseDragged(ModeParameters params) {
				params.transformHelper
						.rotateX((float) (params.yDist / rotateScale));
			}

			public String toString() {
				return "Model Rotate (X)";
			}

		},
		MODEL_ROTATE_Y {

			@Override
			public void mouseDragged(ModeParameters params) {
				if (params.maintainCenter)
					params.transformHelper.rotateAroundUpVector(params.xDist
							/ rotateScale, params.center);
				else
					params.transformHelper.rotateAroundUpVector(params.xDist
							/ rotateScale);
			}

			public String toString() {
				return "Model Rotate (Y)";
			}

		},
		MODEL_ROTATE_Z {

			@Override
			public void mouseDragged(ModeParameters params) {
				params.transformHelper.rotateZ(params.xDist / rotateScale);
			}

			public String toString() {
				return "Model Rotate (Z)";
			}

		},
		MODEL_TRANSLATE_XY {

			@Override
			public void mouseDragged(ModeParameters params) {
				params.transformHelper.translateLeftRight(params.xDist
						/ translateScale);
				params.transformHelper.translateUpDown(params.yDist
						/ translateScale);
			}

			public String toString() {
				return "Model Translate (XY)";
			}

		},
		MODEL_TRANSLATE_ZY {

			@Override
			public void mouseDragged(ModeParameters params) {
				params.transformHelper.translateBackForth(params.xDist
						/ translateScale);
				params.transformHelper.translateUpDown(params.yDist
						/ translateScale);
			}

			public String toString() {
				return "Model Translate (ZY)";
			}

		},
		MODEL_TRANSLATE_XZ {

			@Override
			public void mouseDragged(ModeParameters params) {
				if (params.correctForCamera) {
					params.transformHelper.translateLateral(params.xDist
							/ translateScale, params.cameraPos,
							params.cameraLook);
					params.transformHelper.translateInOut(params.yDist
							/ translateScale, params.cameraPos,
							params.cameraLook);
				} else {
					params.transformHelper.translateLeftRight(params.xDist
							/ translateScale);
					params.transformHelper.translateBackForth(params.yDist
							/ translateScale);
				}
			}

			public String toString() {
				return "Model Translate (XZ)";
			}

		},
		SELECT {

			@Override
			public void mouseDragged(ModeParameters params) {
				// TODO Auto-generated method stub

			}

			@Override
			public boolean isClickMode() {
				return true;
			}

		},REORIENT{
			//TODO possibly just for testing, may not be the best place 
			//for this functionality
			@Override
			public void mouseDragged(ModeParameters params) {
				params.transformHelper.pointNormalDown(params.orientingVector);
			}
		},
		SCALE {

			// TODO
			@Override
			public void mouseDragged(ModeParameters params) {
				
				float dist = (float) Math.sqrt(params.xDist * params.xDist
						+ params.yDist * params.yDist);
				float currScale = params.transformHelper.getScale();
				
				Log.d("SCALE","Current scale: "+currScale);
				
				float theScale;
				
				if (params.xFinal < params.xDown) {
					theScale = currScale - dist / scaleScale;

				} else {
					theScale = currScale + dist / scaleScale;
				}
				Log.d("SCALE","Calculated scale: "+currScale);
				//TODO
				if(theScale>0.25&&theScale<5) params.transformHelper.setScale(theScale);
				if(params.replaceOnSurface){
					float[] mins = new float[4];
					mins[0]=params.mins[0];
					mins[1]=params.mins[1];
					mins[2]=params.mins[2];
					mins[3]=1f;
					
					Log.d("SCALE","Min[1]: "+mins[1]);
					
					
					params.transformHelper.transformPoint(mins);
					Log.d("SCALE","Transformed Min[1]: "+mins[1]);
					float yTran = 0;
					yTran = params.surfacyY - mins[1];
					
					Log.d("SCALE","surface Y: "+params.surfacyY);
					Log.d("SCALE","yTran: "+yTran);
					
					//TODO
					//params.stlController.translateUpDown(yTran);
				}
				
			}
		};

		float translateScale = 15.0f;
		float rotateScale = 40.0f;
		float scaleScale = 190.0f;

		public abstract void mouseDragged(ModeParameters params);

		public static MouseControlMode[] getModes() {
			return new MouseControlMode[] { CAMERA_ROTATE, MODEL_ROTATE_Y,
					MODEL_TRANSLATE_XZ, SELECT, SCALE, REORIENT };
		}

		public boolean isClickMode() {
			return false;
		}

	}

	public class ModeParameters {
		public GeneralSTLTransformHelper transformHelper;
		public GeneralCameraController theCameraController;
		public float xDist;
		public float yDist;
		public float[] center = new float[3];
		public float[] cameraPos = new float[3];
		public float[] cameraLook = new float[3];
		public boolean correctForCamera = false;
		public boolean maintainCenter = false;
		
		public boolean maintainCenterJustXZ = false;//TODO
		public float[] orientingVector = new float[4];//TODO
		
		public boolean replaceOnSurface = true;
		public float surfacyY;
		
		public float xDown;
		public float xFinal;
		public float yDown;
		public float yFinal;
		public float[] maxes = new float[3];
		public float[] mins = new float[3];

	}

	void setCurrentMouseControlMode(MouseControlMode currentSelectedMouseMode);

	void setModel(STLWorkspaceModel theModel);

	MouseControlMode getCurrentMouseControlMode();

}
